perm filename OLDIO.S78[206,LSP]2 blob sn#377377 filedate 1978-09-02 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00005 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	.s(IO,INPUT AND OUTPUT)
C00004 00003	.ss   Basic I/O fucntions.
C00010 00004	.ss        Specifying the Source or Destination for I/O
C00014 00005	.ss  Functions for Selecting and Opening Files.
C00024 ENDMK
C⊗;
.s(IO,INPUT AND OUTPUT)

	There are three components to Input and Output in MACLISP.  First
are the basic functions which read and print.
Some of these deal with S-expressions, others with charaters.
There are also functions to do conversions between characters and ASCII code.
Second there is a collection of switches which can be turned on or
off to control the source of input and the destinations of output.  Typically
the input source is either the terminal or the currently opened file.
Output can go to the terminal, the currently opened file, or both.
Finally there are the functions that select, open and close files.
.ss   Basic I/O fucntions.

.begin indent 0,4
$(READ) reads one S-expression, which is either a list  enclosed  in  matching
parentheses  or  an  atom  delimited  by a special character such as a
space or a parenthesis. (A parenthesis would be saved up and  used  on
the  next call to $READ.)  $READ returns the S-expression which it read,
converting it from the external representation as characters  to  LISP
internal form.  When reading from a file, providing an argument to  $READ 
causes it to return the value of that argument when the end-of-file
is reached  (unless you have specified a fancy eof function).
If no argument is provided, it closes the file and patiently waits for input
from the terminal.

$(READCH)  like read, but reads  in  one  character  and  returns it as a 
character object.

$(TYI) reads in one character and returns  a  number  which  is  the
ASCII code for the character.

$(PRINT_x) prints out the S-expression $x in a form which is readable
by  humans  but  which  could  also  be  read back into LISP if it were
printed to a file rather than to the terminal.  
The expression printed out is preceded by a newline and followed by
a space.  If special characters or strings of characters are used with 
other than their  normal
meanings,  for  example  if  a  parenthesis appears in the pname of an
atom, they are preceded and followed by "|" so that the output  could  be  read
back in.  

$(PRIN1_x) is the same as $(PRINT_x) except that the leading newline
and trailing space are omitted.  $PRIN1 can be used to  print  multiple
items  on  a  line, but spacing between the items must be provided for
explicitly, for example by evaluating $$(TYO 40)$.

$(PRINC_x) is like $(PRIN1_x) except that special characters or
strings of characters are  not surrounded by "|".
This makes the output more
pleasing in certain situations, however it cannot be  read  back  into
LISP.

$(TERPRI) types out a newline.

$(TYO_n) outputs a character whose ASCII code is given by the number $n. 
$PRINC may also be used to output character objects.

.end

	As an example of how some of these reading and printing functions
can be used here is part of a program that is used as a self-documentation
feature in a larger  system.  When the system is loaded it prints a message
telling the user to type $(BBHELP) for information.  $BBHELP prints out
a message explaining itself then does a $READ.  If the user then
types one of the topic names the appropriate message is printed otherwise
an error message is printed.   The "|"s around each line of the message
tell LISP that this is really a single atom. $PRINC prints it as a
character string omitting the "|" delimeters.  $PRINT would retain the "|"s.
.begin nofill 
.select 6

	    (DEFUN  BBHELP ()
		(PROG (TOPIC)
		    (BBMSG)
		HELP
		    (SETQ TOPIC (READ))
		    (COND ((EQ TOPIC 'HELP) (BBHELPER))
			  ((EQ TOPIC 'SYNTAX) (BBSYNHELPER))
			  ((EQ TOPIC 'PUB) (BBPUBHELPER))
			  ((EQ TOPIC 'LPT) (BBLPTHELPER))
			  ((EQ TOPIC 'TXT) (BBTXTHELPER))
			  ((EQ TOPIC 'EXIT) (RETURN 'Bye))
			  (T (BBERRHELPER TOPIC)))     
		    (GO HELP)))


	    (DEFUN BBMSG ()
		(TERPRI)
		(PRINC '|The BB programs convert a list of atoms having |)
		(TERPRI)
		(PRINC '|EXPR FEXPR or VALUE properties to an external form.|)
		(TERPRI)
		(PRINC '|Type HELP to get a list of BBHELP topics|)
		(TERPRI)
		(PRINC '|Type EXIT to get out of BBHELP|)
		(TERPRI))
.end
.ss        Specifying the Source or Destination for I/O

	When  an I/O function is called, the source from which it is
to take its input or the destinations  on which it  is  to  put
its  output are determined by the values of certain global variables
called switches.  The I/O switches are $↑Q, $↑R, and $↑W.  These
switches may be $$SETQ$ed, lambda bound, or set using the $IOC function
as described below.  The switches have the following interpretation:
.begin indent 0,4


$$↑Q$__If  the  value  of $↑Q is qT, the input is taken from the currently
open file.  If $↑Q is qnil, the default input is taken from the
the terminal.   Thus if there is an open file and you set $↑Q to
qT then LISP will read and eval each S-expression in that file.

$$↑R$__If  the  value  of $↑R is qT, the output destinations
include the currently open file.  If it is qnil the output does
not go to the currently open file.

$$↑W$__If the value of $↑W is qT, the output destinations do
not  include  the terminal.  If it is qNIL then output will
go to the terminal.

.end
	The $IOC function can be used to set switches.  It has the basic
form $$(IOC <character>)$.   For I/O switches the following characters
are relevant:
.begin indent 0,4

$$Q$___Sets the switch $↑Q to qT this enabling input from the file
that is currently open. 

$$R$___Sets the switch $↑R to qT enabling output to the currently
open file.

$$S$___Sets the switch $↑Q to qNIL enabling input from the terminal.

$$T$___Sets the switch $↑R to qNIL disabling output to a file.

$$V$___Sets the switch $↑W to qNIL enabling output to the terminal.

$$W$___Sets the switch $↑W to qT disabling output to the terminal.
.end

	Typing <control><char> at the terminal has the same effect as
evaluating $$(IOC_<char>)$.
The file closing functions reset some of the switches.  For example
after reading all the S-expressions in a file, LISP closes the
file and enables input from the terminal.  When an output
file is closed the $↑R switch is reset to qNIL.
.ss  Functions for Selecting and Opening Files.

        The functions $UREAD, $UWRITE, $UAPPEND, and $UFILE together
with certain $STATUS and $SSTATUS functions comprise the file handling
part of the I/O system for Stanford versions of MACLISP.

	File names are represented by a 4-list of the form
.once center

(name1 name2 dev dir)

Name1  and  name2  together  make  up  the "filename," dev is the
"device," and dir is the "directory." 
In  the  DEC-10  implementation, dev is the device name, name1 is
the file name, name2 is the extension, and dir is a list  of  two
fixnums,  the project number and the programmer number.  

	The system maintains a  default 4-list.  The defaults are updated
every time one of the functions $UREAD, $UWRITE, $UAPPEND, or
$UFILE is called, so  that
the  defaults  correspond to  the last file that was used.  The
defaults may be examined by $$(STATUS_CRFILE)$, which returns  the
first  two  elements  of  the default 4-list, and $$(STATUS_CRUNIT)$
which returns the last two.
It is not necessary to specify all four parts  of  the  4-list
when  one of these four functions is used.  Any omitted parts are
taken from the defaults.

	The functions  $UREAD, $UAPPEND, $UWRITE, and $UFILE are  
$$FSUBR$s  which  do  not  evaluate  their
arguments.  They may be applied to a 4-list, e.g.
.once center

$$(APPLY 'UREAD '(FOO BAR DSK COMLAP))$

or they may be called with the 4-list as four arguments, which is
convenient when calling them from top level.  
.BEGIN INDENT 0,4

$UREAD 
This  function  selects  an  input  file.  The argument list is a
4-list as described  above.   The  specified  file  is  made  the
default  input  source.   Note  that  the $↑Q switch mst be turned
on before input will be automatically taken from this file.

$UWRITE/UAPPEND 
These functions open an output file.  When done  with  this  file,  $UFILE 
must  be  used to close it and give it a name.  In the $UWRITE case
a new file is created destroying any oldfile of that name.
In the case of $UAPPEND the output is added on to the end of
and existing file.  The arguments are
the last two elements of a  4-list,  specifying  the  device  and
directory  on  which  the  file  is to be written.  The first two
parts of the 4-list are not specified until the file is ufile'd.

$UFILE 
$$(UFILE name1 name2)$ closes the currently open output file  and  gives  it
the  name  name1.name2.   $(UFILE)  takes name1 and name2 from the
defaults.
.end

	The functions $STATUS AND $SSTATUS examine and set the status
of system variables.  The relevant applications for I/O are the
following.
.begin indent 0,4 

$$(STATUS CRUNIT)$ returns the current (default) device and directory.
It returns qNIL if none has been set.

$$(SSTATUS CRUNIT dev dir)$ sets the defaults for device and directory
to $dev and $dir respectively.

$$(STATUS CRFILE)$ returns the current (default) file name and extension.
It returns qNIL if none has been set.

$$(SSTATUS CRFILE nam ext)$ sets the defaults for file name and extiosion
to $nam and $ext respectively.

$$(STATUS UREAD)$ returns the 4-list naming the currently open input file.
(As set by $$(UREAD nam ext dev dir)$).

$$(SSTATUS UREAD nam ext dev dir)$ has the same effect as 
$$(UREAD nam ext dev dir)$.

$$(STATUS UWRITE)$ returns the device and directory defaults for the currently
open output file (As set by $$(UWRITE nam ext dev dir)$).

$$(SSTATUS UWRITE  dev dir)$ has the same effect as $$(UWRITE dev dir)$.
.end

	As an example of how the file selecting and opening functions can be
used we give here two programs.  $TTYMSG will write the message given it
as an argument on the terminal no matter what the value of the I/O switches
are when it is called.  It saves the current switches, disables output to
a file and enables output to the terminal, $$PRINT$s the message then
restores the switches.
.begin verbatim select 6

	(DEFPROP TTYMSG
	 (LAMBDA(MSG)
	  (PROG (CR CW) (SETQ CR ↑R CW ↑W)
			(SETQ ↑R NIL ↑W NIL)
			(PRINT MSG) 
			(TERPRI)
			(SETQ ↑R CR ↑W CW)))
	EXPR)
.end
The program $BB is the top level of a program to convert a list of function
definitions  to external form.  A typical call to $BB would look like
$$(BB LPT '(BB) BBBB OUT)$.  $LPT specifies a version of external form
suitable for printing on a line printer.  $'(BB) is the list of definitions
to be printed.  In this case $BB will print itself out.  The final two
items specify the file name and extension where the result is to be written.
After some initialization the program opens a file using $UWRITE.  Since
no arguments are provided the current default unit is assumed.  It then
lambda binds $↑R and $↑W to qT thus disabling output to terminal and
enabling output to the file that was opened.  It then calls the 
appropriate version of the converter program (which does the printing).
Finally it closes the file and pops out of the lambda expression thus
restoring the switches to their initial values.  Before exiting it prints
the current values of the device and directory portions of the default
file name list, just so you will know where the file has been written.
.begin verbatim select 6

	(DEFUN BB FEXPR (SPECS)
	  ((LAMBDA (TERPRI BASE *NOPOINT)
	    (PROG (MODE ITEMS FILE BEGINLINE ENDLINE)
		(SETQ MODE (CAR SPECS))
		(SETQ ITEMS (CADR SPECS))
		(SETQ FILE (CDDR SPECS))
		(COND ((EQ MODE 'PUB) (SETQ BEGINLINE '⊗⊗ ENDLINE '⊗))
		      (T  (SETQ BEGINLINE '/  ENDLINE '/ )))
		(UWRITE)
		((LAMBDA (↑R ↑W)
			(COND ((EQ MODE 'LPT) (EVAL (LIST 'BBMCLLPT ITEMS)))
			      ((EQ MODE 'PUB) (EVAL (LIST 'BBMCLPUB ITEMS)))
			      ((EQ MODE 'TXT) (EVAL (LIST 'BBMCLTXT ITEMS)))
			      (T (TTYMSG 'INVALID_MODE)))
			(TERPRI)
			(APPLY 'UFILE FILE)) T T)
		(PRINT (STATUS CRUNIT))))
	    T 10. T))
.end